<?php

class Catalogue_Model_Object_Storage_Table extends Workset_Model_Object_Storage_Table_Abstract {

	protected $_objectClass 		= 'Catalogue_Model_Object';

	protected $_tableClass 			= 'Catalogue_Table_Object';

	protected $_iteratorClass 		= 'Catalogue_Model_Object_Iterator';

	protected $_categoryClass 		= 'Catalogue_Model_Category';

	protected $_categoryTableClass 	= 'Catalogue_Table_Category';

	protected $_attrObjectClass		= 'Catalogue_Model_Attribute';

    protected $_attrTableClass 		= 'Catalogue_Table_Attribute';

	protected $_attrValueTableClass 		= 'Catalogue_Table_Attribute_Value';

    protected $_attrValueEnumTableClass 	= 'Catalogue_Table_Attribute_Value_Enum';

    protected $_objectCategoryTableClass 	= 'Catalogue_Table_Object_Category';

    protected $_linkedObjectTableClass 		= 'Catalogue_Table_Object_Object';

	function setCategoryObjectClass($class) {
		$this->_categoryClass = $class;
	}

	function setCategoryTableClass($class) {
		$this->_categoryTableClass = $class;
	}

	function setAttrTableClass($class) {
		$this->_attrTableClass = $class;
	}

	function setAttrValueTableClass($class) {
		$this->_attrValueTableClass = $class;
	}

	function setAttrValueEnumTableClass($class) {
		$this->_attrValueEnumTableClass = $class;
	}

	function setAttrEnumTableClass($class) {
		$this->_attrEnumTableClass = $class;
	}

	function setObject2CategoryTableClass($class) {
		$this->_objectCategoryTableClass = $class;
	}

	function setObject2ObjectTableClass($class) {
		$this->_linkedObjectTableClass = $class;
	}

	function setOptions(array $options) {
		parent::setOptions($options);

		foreach ($this->_options as $key => $option) {
			switch ($key) {
				case 'categoryObjectClass':
					$this->setCategoryObjectClass($option);
					unset($this->_options[$key]);
				break;

				case 'categoryTableClass':
					$this->setCategoryTableClass($option);
					unset($this->_options[$key]);
				break;

				case 'attrTableClass':
					$this->setAttrEnumTableClass($option);
					unset($this->_options[$key]);
				break;

				case 'attrValueTableClass':
					$this->setAttrValueTableClass($option);
					unset($this->_options[$key]);
				break;

				case 'attrValueEnumTableClass':
					$this->setAttrValueEnumTableClass($option);
					unset($this->_options[$key]);
				break;

				case 'object2CategoryTableClass':
					$this->setObject2CategoryTableClass($option);
					unset($this->_options[$key]);
				break;

				case 'object2ObjectTableClass':
					$this->setObject2ObjectTableClass($option);
					unset($this->_options[$key]);
				break;
			}
		}
	}

    function create($data) {
        if (!isset($data['created'])) {
            $data['created'] = time();
        }
        return parent::create($data);
    }

    function addAttrValue(Workset_Model_Object_Interface $object, $attrId, $valueId, $value, $flags = 0) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            return $row->addDependentRow($this->_attrValueTableClass, array(
                'attr_id' => (int)$attrId,
                'value' => (string)$value,
                'value_id' => (int)$valueId,
                'flag' => $flags
            ));
        }
    }

    function updateAttrValue(Workset_Model_Object_Interface $object, $attrId, $valueId, $value, $flags = 0) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            $valueRow = $row->findDependentRow($this->_attrValueTableClass, 'object', array(
                'attr_id = ?' => (int)$attrId,
            ));
            if ($valueRow) {
                $valueRow->setFromArray(array(
                    'value_id' => (int)$valueId,
                    'value' => (string)$value,
                    'flag' => $flags
                ));
                return $valueRow->save();
            }
        }
    }

	function updateAttrValueById($id, $valueId, $value, $flags = 0) {
		$table = $this->_getTable($this->_attrValueTableClass);
		$row = $table->fetchRow(array(
			"id = ?" => $id
		));
		if ($row instanceof Workset_Db_Table_Row) {
			$row['value'] = $value;
			$row['value_id'] = (int)$valueId;
            $row['flag'] = $flags;

			return $row->save();
		}
	}

    function deleteAttrValues(Workset_Model_Object_Interface $object, $attrId, $valuesId = null) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
			if (is_array($valuesId)) {
				$where = array(
					"attr_id = ?" => (int)$attrId,
					"id in(?)" => $valuesId
				);
			} else {
				$where = array(
					"attr_id = ?" => (int)$attrId
				);
			}

            $select = $this->_getTable()->prepareSelect($where);
            $rowset = $row->findDependentRowset($this->_attrValueTableClass, 'object', $select);

			$del = 0;
			foreach ($rowset as $row) {
				$row->delete();
				$del++;
			}
            return $del;
        }
    }

    function deleteAttrValuesEnum(Workset_Model_Object_Interface $object, $attrId, $valuesId = null) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
			if (is_array($valuesId)) {
				$where = array(
					"attr_id = ?" => (int)$attrId,
					"value_id in(?)" => $valuesId
				);
			} else {
				$where = array(
					"attr_id = ?" => (int)$attrId
				);
			}

            $select = $this->_getTable()->prepareSelect($where);
            $rowset = $row->findDependentRowset($this->_attrValueEnumTableClass, 'object', $select);
			$del = 0;
			foreach ($rowset as $row) {
				$row->delete();
				$del++;
			}
            return $del;
        }
    }

    function addAttrValueEnum(Workset_Model_Object_Interface $object, $attrId, $itemId, $flag = 0) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            return $row->addDependentRow($this->_attrValueEnumTableClass, array(
                'attr_id' => (int)$attrId,
                'value_id' => (int)$itemId,
                'flag' => (int)$flag
            ));
        }
    }

    function updateAttrValueEnum(Workset_Model_Object_Interface $object, $attrId, $oldItemId, $newItemId, $flag = 0) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            $valueRow = $row->findDependentRow($this->_attrValueEnumTableClass, 'object', array(
                'attr_id = ?' => (int)$attrId,
                'value_id = ?' => (int)$oldItemId,
            ));
            if ($valueRow) {
                if ($valueRow['value_id'] != $valueId) {
                    $valueRow->setFromArray(array(
                        'value_id' => (int)$newItemId,
                        'flag' => $flag
                    ));
                    return $valueRow->save();
                } else {
                    return 0;
                }
            }
        }
    }

    function getAttrValues(Workset_Model_Object_Interface $object, $where = null) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            $table = Workset_Db_Table::getStaticTable($this->_attrValueTableClass);

            if (is_array($where)) {
                $where[] = "object_id = {$object->getId()}";
            } else {
                $where = array(
                    "object_id = {$object->getId()}"
                );
            }

            return $table->fetchArray($where);
        }
    }

    function getAttrValuesEnum(Workset_Model_Object_Interface $object) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            $table = Workset_Db_Table::getStaticTable($this->_attrValueEnumTableClass);
            return $table->fetchArray(array(
                "object_id = {$object->getId()}"
            ));
        }
    }

    function linkToObject(Workset_Model_Object_Interface $object, Workset_Model_Object_Interface $refObject) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            return $row->addDependentRow($this->_linkedObjectTableClass, array(
                'object_id' => $refObject->getId(),
            ));
        }
    }

    function unlinkObject(Workset_Model_Object_Interface $object, Workset_Model_Object_Interface $refObject) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            $subrow = $row->findDependentRow($this->_linkedObjectTableClass, 'reference', array(
                'object_id = ?' => $refObject->getId(),
            ));
            if ($subrow) {
                return $subrow->delete();
            }
        }        
    }

    function getObjects(Workset_Model_Object_Interface $object, $where = null, $order = null, $limit = null, $offset = null) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
        	$table = $row->getTable();
			$select = $table->prepareSelect($where, $order, $limit, $offset);

            $rowset = $row->findManyToManyRowset($this->_tableClass, $this->_linkedObjectTableClass, 'object', null, $select);
            return $this->getIterator($rowset, array('countRows' => $this->_countAllRecords, 'filter' => $select));
        }
    }

    function getCategories(Workset_Model_Object_Interface $object, $filter = null, $order = null) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
        	$table = $this->_getTable();
        	$select = $table->prepareSelect($filter, $order);

            $rowset = $row->findManyToManyRowset($this->_categoryTableClass, $this->_objectCategoryTableClass, 'object', null, $select);

            return $this->getIterator($rowset, array(
				'objectClass' => 'Catalogue_Model_Category',
				'storage' => null,
                'countRows' => false,
			));
        }
    }

	function getAllByCategory(Workset_Model_Object_Interface $category, $where = null, $order = null, $limit = null, $offset = null) {
		$row = $category->getData();
        if ($row instanceof Workset_Db_Table_Row) {

			$table = $row->getTable();
			$select = $table->prepareSelect($where, $order, $limit, $offset);

			$rowset = $row->findManyToManyRowset($this->_tableClass, $this->_objectCategoryTableClass, 'category', 'object', $select);

            return $this->getIterator($rowset, array(
                'countRows' => $this->_countAllRecords,
                'filter' => $select
            ));
		}
	}
	
    function getAllByCategories( $categories, $where = null, $order = null, $limit = null, $offset = null, $offsetByPage = false ) {

		if (true == $offsetByPage) {
            $offset = $this->getPageOffset($limit, $offset);
        }
        
        $table = $this->_getTable();
	    $select = $table->prepareSelect($where, $order, $limit, $offset);

        $iselect = $this->_getTable()->select();

        $iselect->from(
            array('m' => $this->_getTable()->info(Zend_Db_Table_Abstract::NAME)),
            array('id' => 'm.id')
        )
       ->join(
            array('i' => $this->_getTable($this->_objectCategoryTableClass )->info(Zend_Db_Table_Abstract::NAME)),
            "i.object_id = m.id",
            array()
        )
        ->where(
            'i.category_id in (?)', $categories
        )
        ->orWhere(
        	'm.category_id in (?)', $categories
        );

        $select->where("id in (?)", new Zend_Db_Expr($iselect->assemble()));
        
        $rowset = $table->fetchAll($select);

        return $this->getIterator($rowset, array(
            'countRows' => $this->_countAllRecords,
            'filter' => $select
        ));

    }

    function setCategoryPriority(Workset_Model_Object_Interface $object,
                                 Workset_Model_Object_Interface $category,
                                 $priority)
    {
        $table = $this->_getTable($this->_objectCategoryTableClass);

        $priority = (int)$priority;

        $result = $table->update(
            array(
                'priority' => $priority
            ),
            array(
                'object_id = ?' => $object->getId(),
                'category_id = ?' => $category->getId()
            )
        );

		$ignore = array($category->getId());

		//базовая категория не учавствует в сортировке
		if ($object->hasCategory()) {
			$ignore[] = $object->getCategoryId();
		}

		$where = array(
			'category_id not in(?)' => $ignore,
			'priority >= ?' => $priority
		);

		$this->updateCategoryPriority($object, $where);
        
        return $result;
    }

	function getMaxCategoryPriority(Workset_Model_Object_Interface $object) {

		$table = $this->_getTable($this->_objectCategoryTableClass);
		$select = $table->getAdapter()->select();
		$name = $table->info(Zend_Db_Table_Abstract::NAME);

		$select	->from($name, array(new Zend_Db_Expr('MAX(priority) as priority')))
        		->where('object_id = ?', $object->getId());

		$result = $table->getAdapter()->fetchOne($select);

		if (false !== $result) {
			return (int)$result;
		} else {
			return 1;
		}
	}

	function getCategoryPriority(Workset_Model_Object_Interface $object,
								 Workset_Model_Object_Interface $category)
	{
		$table = $this->_getTable($this->_objectCategoryTableClass);
		$select = $table->getAdapter()->select();
		$name = $table->info(Zend_Db_Table_Abstract::NAME);

		$select	->from($name, array('priority'))
        		->where('object_id = ?', $object->getId())
				->where('category_id = ?', $category->getId());

		$result = $table->getAdapter()->fetchOne($select);

		if (false !== $result) {
			return (int)$result;
		} else {
			return 1;
		}
	}

	function updateCategoryPriority(Workset_Model_Object_Interface $object, $where = null, $value = null) {
		if (empty($where)) {
			$where = array('object_id = ?' => $object->getId());
		} else {
			$where = (array)$where;
			$where['object_id = ?'] = $object->getId();
		}

		$table = $this->_getTable($this->_objectCategoryTableClass);

		if (empty($value)) {
			$value = 1;
		} else {
			$value = (int)$value;
		}

		return $table->update(
			array(
				'priority' => new Zend_Db_Expr("priority + $value")
			),
			$where
		);
	}

}

?>